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 *~ \#*# 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 { diff --git a/arch/arm/boot/dts/qcom/msm8996-pm.dtsi b/arch/arm/boot/dts/qcom/msm8996-pm.dtsi index bce26c4bbb28..eaa90265619a 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,10 +105,10 @@ 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>; + qcom,min-child-idx = <2>; }; qcom,pm-cluster-level@2{ /* D4 */ @@ -116,10 +116,10 @@ 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,min-child-idx = <1>; + qcom,ss-power = <160>; + qcom,energy-overhead = <441000>; + qcom,time-overhead = <1000>; + qcom,min-child-idx = <2>; qcom,is-reset; }; @@ -134,19 +134,30 @@ 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 = <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 = <700>; - qcom,energy-overhead = <126480>; - qcom,time-overhead = <160>; + qcom,ss-power = <196>; + qcom,energy-overhead = <45300>; + qcom,time-overhead = <210>; }; }; }; @@ -167,9 +178,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,10 +188,10 @@ 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>; + qcom,min-child-idx = <2>; }; qcom,pm-cluster-level@2{ /* D4 */ @@ -188,10 +199,10 @@ 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,min-child-idx = <1>; + qcom,ss-power = <160>; + qcom,energy-overhead = <441000>; + qcom,time-overhead = <1000>; + qcom,min-child-idx = <2>; qcom,is-reset; }; @@ -206,19 +217,30 @@ 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 = <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 = <700>; - qcom,energy-overhead = <136480>; - qcom,time-overhead = <160>; + qcom,ss-power = <196>; + qcom,energy-overhead = <45300>; + qcom,time-overhead = <210>; }; }; }; 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>; 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/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 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 >; }; }; diff --git a/arch/arm64/configs/elementalx_defconfig b/arch/arm64/configs/elementalx_defconfig new file mode 100644 index 000000000000..893cbd2bee6b --- /dev/null +++ b/arch/arm64/configs/elementalx_defconfig @@ -0,0 +1,4437 @@ +# +# 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="-ElementalX-OP3-0.32" +# 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=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 +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 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_IOSCHED_ZEN=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_BFQ is not set +# 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 +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 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 +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_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 + +# +# 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=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 +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=y + +# +# 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_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 +# 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=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 +# 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=y +# 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_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=y +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=y +# 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=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +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_SWEEP2SLEEP=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=y + +# +# 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=y +# 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_MSM_MDSS_KCAL_CTRL=y +# CONFIG_FB_SSD1307 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# 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=y +CONFIG_BACKLIGHT_GENERIC=y +# 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_SOUND_CONTROL=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=y +CONFIG_SONY_FF=y +# 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 is not set + +# +# 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 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 +# +CONFIG_MSM_AVTIMER=y +CONFIG_MSM_BUS_SCALING=y +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_SDCARD_FS=y +CONFIG_SDCARD_FS_XATTR=y +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=y +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=y +# 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 diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 24dbef75316f..c451649d77dc 100755 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -494,7 +494,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 48d5ff717c65..870aa197321b 100755 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -514,7 +514,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/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); + } } /* 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 }; diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index af3d6a330982..fa0689ea4d6d 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 @@ -50,6 +68,34 @@ 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. + +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 @@ -63,16 +109,39 @@ 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" + config DEFAULT_SIO + bool "SIO" if IOSCHED_SIO=y + + config DEFAULT_FIOPS + bool "FIOPS" if IOSCHED_FIOPS=y + + config DEFAULT_ZEN + bool "ZEN" if IOSCHED_ZEN=y + endchoice 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 + default "zen" if DEFAULT_ZEN endmenu diff --git a/block/Makefile b/block/Makefile index ba63d68fe91d..2e5c330fec8c 100644 --- a/block/Makefile +++ b/block/Makefile @@ -19,6 +19,10 @@ 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_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/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..71b51c1b436c --- /dev/null +++ b/block/bfq-iosched.c @@ -0,0 +1,4218 @@ +/* + * 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; +} + +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) +{ + 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, coop_or_in_burst, + 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; + } + + 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 && + !coop_or_in_burst && + time_is_before_jiffies(bfqq->soft_rt_next_start); + 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)); + + 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 (bfq_bfqq_just_split(bfqq)) + goto set_ioprio_changed; + + /* + * 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) && + (!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); + 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 (coop_or_in_burst || + (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; + } + } +set_ioprio_changed: + 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 inline sector_t bfq_io_struct_pos(void *io_struct, bool request) +{ + if (request) + return blk_rq_pos(io_struct); + else + return ((struct bio *)io_struct)->bi_iter.bi_sector; +} + +static inline sector_t bfq_dist_from(sector_t pos1, + sector_t pos2) +{ + if (pos1 >= pos2) + return pos1 - pos2; + else + return pos2 - pos1; +} + +static inline int bfq_rq_close_to_sector(void *io_struct, bool request, + sector_t sector) +{ + 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, sector_t sector) +{ + struct rb_root *root = &bfqd->rq_pos_tree; + struct rb_node *parent, *node; + struct bfq_queue *__bfqq; + + 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_to_sector(__bfqq->next_rq, true, sector)) + 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_to_sector(__bfqq->next_rq, true, sector)) + 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 + * 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, + sector_t sector) +{ + 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, sector); + 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; +} + +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 + * 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; +} + +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; + 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 (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); + } + goto keep_queue; + } + } + + /* + * 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 (timer_pending(&bfqd->idle_slice_timer) || + (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq))) { + bfqq = NULL; + goto keep_queue; + } + + reason = BFQ_BFQQ_NO_MORE_REQUESTS; +expire: + bfq_bfqq_expire(bfqd, bfqq, 0, reason); +new_queue: + 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) +{ + 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(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 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; + 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); + } + } + /* 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); +} + +/* + * 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; + /* + * 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) +{ + 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]) { + /* + * 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; + } +} + +/* + * 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; + + /* 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 || + 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_clear_bfqq_just_split(bfqq); + + 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), *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); + + 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); + } +} + +/* + * 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"); + + put_io_context(bic->icq.ioc); + + 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; + bool split = false; + + 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); + 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 (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; + } + } + + 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; + + /* + * 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; + +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..d0890c6d4c11 --- /dev/null +++ b/block/bfq-sched.c @@ -0,0 +1,1180 @@ +/* + * 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; +} + +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..629c413c16ab --- /dev/null +++ b/block/bfq.h @@ -0,0 +1,807 @@ +/* + * 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 + * @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). + * 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; + struct bfq_io_cq *bic; + + /* 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 + * @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 { + 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 split */ + BFQ_BFQQ_FLAG_just_split, /* queue has just been split */ +}; + +#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(just_split); +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 */ 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; } diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5da8e6e9ab4b..a8ad4f16e10a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -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/block/fiops-iosched.c b/block/fiops-iosched.c new file mode 100644 index 000000000000..a7fcb6fb8f7e --- /dev/null +++ b/block/fiops-iosched.c @@ -0,0 +1,763 @@ +/* + * 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->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) { + return elv_rb_find(&cic->sort_list, bio_end_sector(bio)); + } + + 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..a2f8249c7ed7 --- /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(next->fifo_time, rq->fifo_time)) { + list_move(&rq->queuelist, &next->queuelist); + rq->fifo_time = next->fifo_time; + } + } + + /* 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->fifo_time = 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)) + 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"); + diff --git a/block/zen-iosched.c b/block/zen-iosched.c new file mode 100644 index 000000000000..2d3e11d1add4 --- /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 = 16; + +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"); 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; 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; 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/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index cfc8cbf22278..ba4f9ab4f10f 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2051,9 +2051,15 @@ 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++) { + 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; diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index a54eb5dea527..b4e84e791631 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, @@ -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; } diff --git a/drivers/clk/msm/clock-cpu-8996.c b/drivers/clk/msm/clock-cpu-8996.c index e0779cf63e84..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); @@ -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[] = { 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; 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; } 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 36949f4b3f14..c1df97fa3554 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); @@ -207,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; } @@ -218,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); } @@ -231,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); } @@ -333,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)] = { @@ -1168,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; @@ -2422,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); @@ -2477,7 +2500,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 +2511,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 +2529,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 +2912,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 +2972,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 +2982,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 +3014,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 +3035,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 +3063,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 +4538,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 +4575,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 +4699,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 +4737,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 +4784,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 +4976,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 +5017,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 +5057,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 +5153,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 +5185,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 +5258,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 +5287,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 +5382,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 +5408,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 +5498,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 +5523,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 +5585,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 +5605,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 +5971,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 +5980,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..8bdf9da4d654 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, @@ -714,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; @@ -731,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; @@ -1050,6 +1086,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 +1208,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 +1227,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 +1242,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 +1259,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 +1484,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 +1511,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 +1520,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 +1545,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 +1571,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 +1581,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 +1636,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 +1713,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 +1758,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 +1904,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 +2365,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 +2453,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 +2461,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 +2484,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 +2501,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 +2560,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 +2587,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; } @@ -3893,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) { @@ -3914,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); @@ -3923,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; @@ -5082,6 +5217,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 +5227,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 +5753,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 +5761,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 +5836,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); } 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__); diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index 5ebd32fbb38d..7a111e43749e 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -56,6 +56,10 @@ static DEFINE_SPINLOCK(suspend_lock); #define TAG "msm_adreno_tz: " +#if 1 +static unsigned int adrenoboost = 0; +#endif + static u64 suspend_time; static u64 suspend_start; static unsigned long acc_total, acc_relative_busy; @@ -86,6 +90,31 @@ u64 suspend_time_ms(void) return time_diff; } +#if 1 +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 > 3) { + adrenoboost = 0; + } else { + adrenoboost = input; + } + + return count; +} +#endif + static ssize_t gpu_load_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -131,6 +160,11 @@ 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); static DEVICE_ATTR(suspend_time, 0444, @@ -140,6 +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 }; @@ -285,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); 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/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 c93737a19d63..a97adb437526 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -4026,6 +4026,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"); @@ -4089,6 +4091,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; } 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, 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; } /* 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"); + 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) 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/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; 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; } 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..35a8395f8a26 --- /dev/null +++ b/drivers/input/touchscreen/sweep2sleep.c @@ -0,0 +1,340 @@ +#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; + +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) { + + 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; + + 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__); + + 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); diff --git a/drivers/input/touchscreen/synaptics_driver_s1302.c b/drivers/input/touchscreen/synaptics_driver_s1302.c index b3521addda36..d739d0990db0 100755 --- a/drivers/input/touchscreen/synaptics_driver_s1302.c +++ b/drivers/input/touchscreen/synaptics_driver_s1302.c @@ -300,6 +300,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) @@ -922,7 +924,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 } @@ -1981,6 +1983,80 @@ 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) +{ + 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 choice_gpio_function(struct synaptics_ts_data *ts) { int ret=0; @@ -2153,6 +2229,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; diff --git a/drivers/input/touchscreen/synaptics_driver_s3320.c b/drivers/input/touchscreen/synaptics_driver_s3320.c index c4a75f601305..285c3a4fb6d3 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 @@ -1237,9 +1253,62 @@ 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)){ +#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); @@ -2424,9 +2493,11 @@ static int synaptics_input_init(struct synaptics_ts_data *ts) set_bit(ABS_MT_POSITION_X, ts->input_dev->absbit); set_bit(ABS_MT_POSITION_Y, ts->input_dev->absbit); set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); - set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit); #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); #ifdef VENDOR_EDIT_OXYGEN set_bit(KEY_DOUBLE_TAP, ts->input_dev->keybit); set_bit(KEY_GESTURE_CIRCLE, ts->input_dev->keybit); @@ -2436,6 +2507,8 @@ static int synaptics_input_init(struct synaptics_ts_data *ts) set_bit(KEY_GESTURE_RIGHT_V, ts->input_dev->keybit); #endif #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_TOUCH_MINOR, 0,255, 0, 0); @@ -3886,6 +3959,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 @@ -3983,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; @@ -4115,9 +4270,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: @@ -4347,7 +4545,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__); 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; } diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index 888b1180b981..82d175b04a15 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,110 @@ #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 +#define LED_CUSTOM_PWM_US 1000 + + +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; +} + +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) || + (strcmp(led_cdev->name, "green") == 0) || + (strcmp(led_cdev->name, "blue") == 0)) + return 1; + + return 0; +} + +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 @@ -1810,7 +1916,11 @@ 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; + 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); else @@ -2204,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; @@ -2259,6 +2372,9 @@ static ssize_t pause_lo_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); + if (check_for_notification_led(led_cdev)) + pause_lo = convert_pause_lo_store(pause_lo); + switch (led->id) { case QPNP_ID_LED_MPP: pwm_cfg = led->mpp_cfg->pwm_cfg; @@ -2314,6 +2430,9 @@ static ssize_t pause_hi_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); + if (check_for_notification_led(led_cdev)) + pause_hi = convert_pause_hi_store(pause_hi); + switch (led->id) { case QPNP_ID_LED_MPP: pwm_cfg = led->mpp_cfg->pwm_cfg; @@ -2425,6 +2544,9 @@ static ssize_t ramp_step_ms_store(struct device *dev, return ret; led = container_of(led_cdev, struct qpnp_led_data, cdev); + 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: pwm_cfg = led->mpp_cfg->pwm_cfg; @@ -2678,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); @@ -2685,7 +2820,22 @@ 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 (check_for_notification_led(led_cdev)) + { + 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); + } + } + else + led_blink(led, led->rgb_cfg->pwm_cfg); + break; case QPNP_ID_KPDBL: led_blink(led, led->kpdbl_cfg->pwm_cfg); @@ -2697,6 +2847,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 +2937,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 +2963,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[] = { 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"; 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; 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; } 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; } 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_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; 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; 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; 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); 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); /* 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) { 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/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) { diff --git a/drivers/platform/msm/qpnp-haptic.c b/drivers/platform/msm/qpnp-haptic.c index caaef7d207c0..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) { @@ -1294,6 +1293,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 +1378,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) @@ -1485,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); @@ -1498,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); @@ -1510,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) { /* @@ -1526,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, @@ -1545,6 +1593,7 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on) } } + mutex_unlock(&hap->set_lock); return rc; } @@ -1553,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); @@ -1569,6 +1619,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; @@ -1576,9 +1632,16 @@ 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) +{ + qpnp_hap_td_enable(&ghap->timed_dev, value); } /* play pwm bytes */ @@ -2228,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); diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c index 91f8ca2fdb9e..040ae45d8a06 100644 --- a/drivers/platform/msm/qpnp-power-on.c +++ b/drivers/platform/msm/qpnp-power-on.c @@ -157,6 +157,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, @@ -1602,6 +1606,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++) { 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/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c index 71f2810713aa..415508c13d1a 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 2: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) 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; 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; \ 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/android/binder.c b/drivers/staging/android/binder.c index a6cd39586d75..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); @@ -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; @@ -2087,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) { @@ -2896,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; } } @@ -2928,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; @@ -3154,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]); @@ -3233,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, @@ -3247,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); } @@ -3255,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"); @@ -3358,7 +3363,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); } 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..c96f7be08a18 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/HTT/htt_tx.c @@ -0,0 +1,941 @@ +/* + * 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 + +#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; + 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 = + 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++; + } + + /* + * 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; + +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..7d36602b6646 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TLSHIM/tl_shim.c @@ -0,0 +1,2639 @@ +/* + * 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); + + /* 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 = + 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; + 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); + 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); + 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) { + 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 + * + * Return: VOS_STATUS + */ +VOS_STATUS 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 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 VOS_STATUS_E_FAILURE; + } + + vdev = tl_shim->session_flow_control[sessionId].vdev; + if (!vdev) { + TLSHIM_LOGE("%s, vdev is NULL", __func__); + return VOS_STATUS_E_FAILURE; + } + return ol_txrx_stats(vdev, buffer, (unsigned)length); +} + +/*============================================================================= + 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..2385e3455e74 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_tx_queue.c @@ -0,0 +1,1944 @@ +/* + * 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; + } + + 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; + 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..68ca4cec2b79 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/CLD_TXRX/TXRX/ol_txrx.c @@ -0,0 +1,2638 @@ +/* + * 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: VOS_STATUS + */ +VOS_STATUS +ol_txrx_stats(ol_txrx_vdev_handle vdev, char *buffer, unsigned buf_len) +{ + int ret; + + ret = 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 (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 +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..593edf0b42f5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/EPPING/src/epping_main.c @@ -0,0 +1,431 @@ +/* + * 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 "wlan_hdd_memdump.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; + } + memdump_deinit(); + 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 */ + memdump_init(); + 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..2c8e556f96f0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/qc_sap_ioctl.h @@ -0,0 +1,277 @@ +/* + * 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 _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_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..8a500506fe30 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_assoc.h @@ -0,0 +1,174 @@ +/* + * 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. + */ + +#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 + +/* 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.*/ + 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, 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, + 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..4958056d7f38 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h @@ -0,0 +1,4274 @@ +/* + * 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) + +/* + * 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 (0) +#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 ( 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 ( 30 ) + +#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 ) + +/* 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 ) +#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 ) + +/* 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 ) +#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 */ + +/* + * 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 (3) +#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) + +/* + * 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 + -------------------------------------------------------------------------*/ + +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_U8_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; + uint16_t sap_tx_leakage_threshold; + /* parameter to control GTX */ + uint32_t tgt_gtx_usr_cfg; +} 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..985297b79711 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -0,0 +1,1760 @@ +/* + * 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, + QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT, + /* 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 + +#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 locally_generated, + int reason) +{ + cfg80211_disconnected(dev, reason, NULL, 0, + locally_generated, GFP_KERNEL); +} +#else +static inline void wlan_hdd_cfg80211_indicate_disconnect(struct net_device *dev, + bool locally_generated, + 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_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..72df9c0bb848 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_main.h @@ -0,0 +1,1973 @@ +/* + * 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 5000 +#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 800 + +#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 +/* 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 + +#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; + tSirPeerInfoRspParams ibss_peer_info; + + 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 + + struct completion ibss_peer_info_comp; + + /* 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; + bool memdump_init_done; +#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; + /* + * 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; +}; + +/*--------------------------------------------------------------------------- + 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 + +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); + +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, + 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); +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 *); +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_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..c56e384c948d --- /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 800 + +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..249674dd3059 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_p2p.h @@ -0,0 +1,197 @@ +/* + * 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 __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_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); + +#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..b181f130e5aa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tdls.h @@ -0,0 +1,458 @@ +/* + * 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; + 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; + uint8_t qos; + 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, + bool is_qos_wmm_sta); + +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); + +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, + 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; +} +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 new file mode 100644 index 000000000000..c39d27f81aeb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_tgt_cfg.h @@ -0,0 +1,117 @@ +/* + * 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. + */ + +#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; + uint32_t fine_time_measurement_cap; +}; + +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..e18f7f25b663 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_wext.h @@ -0,0 +1,483 @@ +/* + * 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 __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; + +/** 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 + /* Wireless statistics */ + struct iw_statistics iw_stats; +}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 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); + +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..5e01b79c7eec --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_assoc.c @@ -0,0 +1,5345 @@ +/* + * 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_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 + +#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, + 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; + } + +} + +/** + * 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) +{ + 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) + { + /* 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 + { + // 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 diconnect handler 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); + wlan_hdd_cfg80211_indicate_disconnect(dev, false, + pRoamInfo->reasonCode); + } + else + wlan_hdd_cfg80211_indicate_disconnect(dev, false, + WLAN_REASON_UNSPECIFIED); + + 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 (hdd_unset_beacon_filter(pAdapter) != 0) + hddLog(LOGE, + FL("hdd_unset_beacon_filter() failed")); + + 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; + u16 reason_code; +#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 ); + + 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 ) + { + 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, pRoamInfo, + 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 " result:%d and Status:%d", + __func__, MAC_ADDR_ARRAY(pRoamInfo->bssid), + roamResult, roamStatus); + + /* inform connect result to nl80211 */ + hdd_connect_result(dev, pRoamInfo->bssid, pRoamInfo, + 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 + " result:%d and Status:%d\n", + MAC_ADDR_ARRAY(pRoamInfo->bssid), + roamResult, roamStatus); + else + pr_info("wlan: connection failed with " MAC_ADDRESS_STR + " result:%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" result:%d and Status:%d reasonCode %d" , + __func__, MAC_ADDR_ARRAY(pRoamInfo->bssid), + roamResult, roamStatus, pRoamInfo->reasonCode); + else + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: connect failed: for bssid " MAC_ADDRESS_STR " result:%d and Status:%d " , + __func__, MAC_ADDR_ARRAY(pWextState->req_bssId), + roamResult, roamStatus); + + /* inform association failure event to nl80211 */ + if ( eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL == roamResult ) + { + if (pRoamInfo) + 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, NULL, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + } + else + { + 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) { + 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 + + 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( +#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, 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; + 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 ..*/ + staDesc.ucQosEnabled = qos; + + 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 ); +} + +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); + } + pHddTdlsCtx->curr_candidate = curr_peer; + + wlan_hdd_tdls_implicit_send_discovery_request(pHddTdlsCtx); + } + 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_REMAIN_CHAN_READY: + hdd_remainChanReadyHandler( pAdapter ); + 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..1a669d9bfa3e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg.c @@ -0,0 +1,7256 @@ +/* + * 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), + + 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 +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); + + 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 +#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; + uint32_t 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"); + } + + 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; +} + + +/**--------------------------------------------------------------------------- + + \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..492db4e42068 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -0,0 +1,23355 @@ +/* + * 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; + u32 ftm_capab; + 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_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]); + + 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, + .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) && + ((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; + } + + 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(); + /* 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 + 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; + } + + 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)) + { + 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)); + + + 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); + + 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; + + 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; + bool is_qos_wmm_sta = false; +#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; + } + } + + 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, + is_qos_wmm_sta); + 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; + uint8_t num_chan = 0; + + 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++ ) + { + 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); + + } + + 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 */ + 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; + /* + * 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: + 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 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; + } + + /* 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); + + 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")); + + wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true, + WLAN_REASON_UNSPECIFIED); +#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; + tSirUpdateIE updateIE; + + 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; + } + + /* 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), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_IBSS_LEAVE); + if (!HAL_STATUS_SUCCESS(hal_status)) { + hddLog(LOGE, + FL("sme_RoamDisconnect failed hal_status(%d)"), hal_status); + return -EAGAIN; + } + status = wait_for_completion_timeout( + &pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + if (!status) { + hddLog(LOGE, + FL("wait on disconnect_comp_var failed")); + return -ETIMEDOUT;; + } + + EXIT(); + return 0; +} + +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; + } + + 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 ; + } + } + } + + if (!num_ch) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%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 */ + 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_SETUP_CNF== 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: %s rc %ld mgmtTxCompletionStatus %u", + __func__, + !rc ? "Mgmt Tx Completion timed out" :"Mgmt Tx Completion failed", + rc, 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; + } + + 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) { + + 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); + + 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, + tdlsLinkEstablishParams.qos); + 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..c59b0fc5e8bf --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -0,0 +1,2290 @@ +/* + * 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 +#include + +/**----------------------------------------------------------------------------- +* 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__); + + /* 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__); + } + +#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; +} + + + +/* 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); + + /* 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); +#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..b4958e9bf554 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_hostapd.c @@ -0,0 +1,7134 @@ +/* + * 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_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 = 0; + + 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_REMAIN_CHAN_READY: + hdd_remainChanReadyHandler( pHostapdAdapter ); + 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; + } + + 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")); + 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; + + 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: + 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 = snprintf(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) { + 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; + 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: + { + return hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), + extra, WE_MAX_STR_LEN); + } + } + 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_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; + int is_dfs_mode_enabled = 0; + + 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; + } + 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 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) || + (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); + + channel_list->num_channels = num_channels; + EXIT(); + + return 0; +} + +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_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 int +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 = 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; + + 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]); + if (len >= buf_len) { + hddLog(LOGE, FL("Insufficient buffer:%d, %d"), buf_len, len); + return -E2BIG; + } + pBuf += len; + buf_len -= len; + } + if(WE_GET_STA_INFO_SIZE > buf_len) + { + break; + } + } + 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) +{ + 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; + + ret = hdd_softap_get_sta_info(pHostapdAdapter, extra, WE_SAP_MAX_STA_INFO); + if (ret) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!",__func__); + return ret; + } + 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 -1] = '\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_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..7101626e666c --- /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_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_v6].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 (!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; + } + + 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 */ + 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..0e34590da5c6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_main.c @@ -0,0 +1,17096 @@ +/* + * 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 */ + +/* + * 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 +#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 + +#define WLAN_NLINK_CESIUM 30 + +/* + * 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); + +/* 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; +#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); + } + +} + +/* 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) +{ + /* 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 int payload_len, const tANI_U8 *payload) +{ + struct ieee80211_channel chan; + int frame_len, ret = 0; + tANI_U8 *frame; + struct ieee80211_hdr_3addr *hdr; + u64 cookie; + hdd_station_ctx_t *pHddStaCtx; + hdd_context_t *pHddCtx; + 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; +} + +/** + * 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; + + /* The params are located after "SENDACTIONFRAME " */ + total_len -= 16; + params = (struct android_wifi_af_params *)(command + 16); + + 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; + } + + if (!mac_pton(params->bssid, (u8 *)&bssid)) { + hddLog(LOGE, FL("MAC address parsing failed")); + return -EINVAL; + } + + if (params->channel < 0 || + params->channel > WNI_CFG_CURRENT_CHANNEL_STAMAX) { + hddLog(LOGE, FL("Invalid channel: %d"), params->channel); + return -EINVAL; + } + + if (params->dwell_time < 0) { + hddLog(LOGE, FL("Invalid dwell_time: %d"), params->dwell_time); + return -EINVAL; + } + + ret = hdd_sendactionframe(pAdapter, bssid, params->channel, + params->dwell_time, params->len, params->data); + + 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 total_len) +{ + 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 + * + * 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, total_len); + } + + 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 */ + +#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; + + content = VOS_MIN(content, WNI_CFG_VALID_CHANNEL_LIST_LEN); + pPlmRequest->plmNumCh = content; + hddLog(LOG1, FL("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 || content <= 0 || + content > WNI_CFG_CURRENT_CHANNEL_STAMAX) + 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; +} +/** + * 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) +{ + 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; +} + +/* 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 + * @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; + uint8_t input = 0; + uint32_t 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 Number of IE fields */ + v = sscanf(inPtr, "%31s ", buf); + if (1 != v) return -EINVAL; + + v = kstrtou8(buf, 10, &input); + if (v < 0) return -EINVAL; + + input = VOS_MIN(input, SIR_ESE_MAX_MEAS_IE_REQS); + pEseBcnReq->numBcnReqIe = input; + + hddLog(LOG1, "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 = kstrtou32(buf, 10, &tempInt); + if (v < 0) return -EINVAL; + + switch (i) { + case 0: /* Measurement token */ + if (!tempInt) { + 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) || + (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) && + (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); + 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, j; + 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, j = 0; i < adapter->mc_addr_list.mc_cnt; i++) { + if (!memcmp(adapter->mc_addr_list.addr[i], + &pattern, 1)) { + memcpy(filter->multicastAddr[j], + adapter->mc_addr_list.addr[i], + sizeof(adapter->mc_addr_list.addr[i])); + hddLog(LOG1, "%s RX filter : addr =" + MAC_ADDRESS_STR, + action ? "setting" : "clearing", + MAC_ADDR_ARRAY(filter->multicastAddr[j])); + j++; + } + } + filter->ulMulticastAddrCnt = j; + /* 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, + priv_data.total_len); + } + 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))) + { + 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, + 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; + + pPlmRequest = vos_mem_malloc(sizeof(tSirPlmReq)); + if (NULL == pPlmRequest){ + ret = -ENOMEM; + 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 ((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: copy data to user buffer failed GETIBSSPEERINFO command", + __func__); + ret = -EFAULT; + goto exit; + } + } + 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; + } + + /* 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) + { + 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); + } + 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) + { + 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 &= (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; + } + 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); + 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 + * 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; + v_BOOL_t in_standby = TRUE; + + MTRACE(vos_trace(VOS_MODULE_ID_HDD, TRACE_CODE_HDD_OPEN_REQUEST, + pAdapter->sessionId, pAdapter->device_mode)); + + /* 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); + 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 0; +} + +/** + * 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; + pAdapter->pHddCtx = NULL; + + 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); + } +} + +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() - + + 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(&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); + 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; +} + +/** + * 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; + 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 + * @roam_info: information about connected bss + * @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 + */ +#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, + 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); +} +#endif + +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 */ + wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, false, + WLAN_REASON_UNSPECIFIED); + } + 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, + 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_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; + 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_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); +#else + nl_srv_exit(); +#endif /* WLAN_KD_READY_NOTIFIER */ + + hdd_close_cesium_nl_sock(); + + 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); + + hdd_close_tx_queues(pHddCtx); + //Do all the cleanup before deregistering the driver + memdump_deinit(); + 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; + + memdump_init(); + 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); + + 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 ) ) + { + 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 + + 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) + { + 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 */ + + hdd_close_cesium_nl_sock(); + +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 { + 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__); + + 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..f3b6c6ef0229 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_memdump.c @@ -0,0 +1,677 @@ +/* + * 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); + hdd_ctx->memdump_init_done = true; + + 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; + } + + 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")); + 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); + mutex_destroy(&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..14eb877b02b0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_oemdata.c @@ -0,0 +1,850 @@ +/* + * 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. + */ + +#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)); + + 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__); + + status = sme_OemDataReq(pHddCtx->hHal, + pAdapter->sessionId, + &oemDataReqConfig, + &oemDataReqID); + + vos_mem_free(oemDataReqConfig.data); + 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..d1040bb8d6b5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_p2p.c @@ -0,0 +1,2895 @@ +/* + * 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_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); + + 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(); + } + 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' + * 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; + 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 ) + ) + { + 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 ); + + } + + mutex_lock(&cfgState->remain_on_chan_ctx_lock); + 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 ); + 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); + 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 (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); + 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 == 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")); + /* + * 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) && + (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))) { + home_ch = pAdapter->sessionCtx.ap.operatingChannel; + } 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 && + (test_bit(SOFTAP_BSS_STARTED, &goAdapter->event_flags))) + 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 != NULL) && + (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_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 + * + *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_indicate_mgmt_frame(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..ca400e540cee --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tdls.c @@ -0,0 +1,3246 @@ +/* + * 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 "wlan_hdd_assoc.h" +#include "sme_Api.h" +#include "vos_sched.h" + +/** + * 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; + 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) { + 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 + * 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); + + /* 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) + 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); + + /* Indicate teardown to supplicant */ + wlan_hdd_tdls_indicate_teardown( + 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); +} + +/** + * 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); +} + +/* 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, + bool del_forced_peer) +{ + 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); + /* 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; + } + } +} + +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_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_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, true); + + 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, + bool is_qos_wmm_sta) +{ + 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; + + curr_peer->qos = is_qos_wmm_sta; + + 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; + + tdlsLinkEstablishParams->qos = curr_peer->qos; + + 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, false); + + 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; +} + +void wlan_hdd_tdls_implicit_send_discovery_request(tdlsCtx_t * pHddTdlsCtx) +{ + hdd_context_t *pHddCtx; + hddTdlsPeer_t *curr_peer; + hddTdlsPeer_t *temp_peer; + tSirMacAddr peer_mac; + + ENTER(); + + if (NULL == pHddTdlsCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + FL("pHddTdlsCtx is NULL")); + 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); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Implicit TDLS, Send Discovery request event", __func__); + + cfg80211_tdls_oper_request(pHddTdlsCtx->pAdapter->dev, + curr_peer->peerMac, + NL80211_TDLS_DISCOVERY_REQ, + FALSE, + GFP_KERNEL); + + mutex_lock(&pHddCtx->tdls_lock); + + 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; +} + +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..93f0e6f30196 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -0,0 +1,2076 @@ +/* + * 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) +{ +#if defined( WLAN_DEBUG ) + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); +#endif + 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..fbeaa482988e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_wext.c @@ -0,0 +1,12794 @@ +/* + * 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_IBSS_STA_INFO 11 +#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_IBSS_GET_PEER_INFO_ALL 10 +#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_IBSS_GET_PEER_INFO 6 +#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 - zero on success, non zero value on failure + + --------------------------------------------------------------------------*/ +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, ret; + VOS_STATUS status; + + 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); + + if (len >= buf_len) { + hddLog(LOGE,FL("Insufficient buffer:%d, %d"), buf_len, len); + return -E2BIG; + } + + for (i = 0; i < NUM_CPUS; i++) { + 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; + } + + ret = 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 + ); + + 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; +} + +/**--------------------------------------------------------------------------- + + \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; +} + +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); + 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; + 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; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + 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: 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(); + + 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); +} + +/** + * 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}; + + 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__); + 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)) { + hddLog(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; + + 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__); + 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; + + 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: + { + 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: + { + return hdd_wlan_get_stats(pAdapter, &(wrqu->data.length), + extra, WE_MAX_STR_LEN); + } + +/* 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_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_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; + 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_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); + 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; + 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_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: + { + 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 = 0; + 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_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, + "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_IBSS_GET_PEER_INFO_ALL, + 0, + 0, + "ibssPeerInfoAll" }, + { 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" }, + { 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, + 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..f5ecebefa911 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/aniGlobal.h @@ -0,0 +1,1286 @@ +/* + * 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. + */ + + +/* + * 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, +}; + +/* 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, + 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; + uint32_t tdls_frm_session_id; + 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; + sir_mgmt_frame_ind_callback mgmt_frame_ind_cb; + sir_p2p_ack_ind_callback p2p_ack_ind_cb; +} 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..95b5be903ee3 --- /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 76 + +#define QWLAN_VERSIONSTR "4.4.31.76" + + +#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..fd3b24fe1ab9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/sirApi.h @@ -0,0 +1,6614 @@ +/* + * 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; + uint8_t data_len; + uint8_t *data; +} 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 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 + 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 +{ + uint16_t frame_len; + tANI_U32 rxChan; + tANI_U8 sessionId; + tANI_U8 frameType; + tANI_S8 rxRssi; + 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 +{ + 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 +{ + uint16_t message_type; + uint16_t length; + 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; + +#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; + +/*--------------------------------------------------------------------------- +* 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 +{ + 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; + int32_t oui_length; + +}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 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 + * @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; +}; + + +/** + * 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/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..0635735b8ba6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniApi.h @@ -0,0 +1,731 @@ +/* + * 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_REMAIN_ON_CHN_RDY_IND, + eWNI_SME_SEND_ACTION_FRAME_IND, + 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_IBSS_PEER_INFO_RSP, + 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_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 +}; + +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..a99db6140104 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgAp.h @@ -0,0 +1,2531 @@ +/* + * 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. + */ + +/* + * 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 +#define WNI_CFG_TGT_GTX_USR_CFG 298 + +/* + * 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 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 242 +#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..cfeafbc91051 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/wniCfgSta.h @@ -0,0 +1,1620 @@ +/* + * 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. + */ + +/* + * 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 +#define WNI_CFG_TGT_GTX_USR_CFG 298 + +/* + * 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 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 + +#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..87cd511ddeec --- /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, LOG1, "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..b14ee505cfd0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/cfg/cfgProcMsg.c @@ -0,0 +1,2985 @@ +/* + * 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 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}, + + {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] = { + {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..6184e10b27da --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/parserApi.h @@ -0,0 +1,1010 @@ +/* + * 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.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; + tDot11fIEExtCap ExtCap; + 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, + uint8_t curr_oper_channel); + +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..ed0a40cd171a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/include/sirParams.h @@ -0,0 +1,916 @@ +/* + * 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) + +/* 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) + +#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) + +#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) +#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_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) + +#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_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) + +// 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..558f39eeaa56 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limApi.h @@ -0,0 +1,268 @@ +/* + * 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 *); +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. + */ +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..af37b2b7882f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limGlobal.h @@ -0,0 +1,724 @@ +/* + * 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; + uint8_t data_len; + uint8_t *data; +} 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..e3809d2b1b6b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/include/limSession.h @@ -0,0 +1,643 @@ +/* + * 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; + bool is_ext_caps_present; +} 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..c95e5bf7a23a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limApi.c @@ -0,0 +1,2700 @@ +/* + * 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 + pMac->lim.gpLimMlmOemDataReq = NULL; +} + +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.tdls_frm_session_id = 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) { + 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; + } + + 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() ***/ + +/** + * 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); +} + +/*-------------------------------------------------------------------------- + + \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..efe9c52c6825 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limAssocUtils.c @@ -0,0 +1,5002 @@ +/* + * 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)) { + limDelSta(pMac, pStaDs, false, 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); + + /* 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; + 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); + 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..258208fbd30a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c @@ -0,0 +1,2064 @@ +/* + * 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; + VOS_STATUS vosStatus; + + 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; + + 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) + { + 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->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); +} + +/*------------------------------------------------------------------ + * + * 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; + 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);) + + /* 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; + } + + 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*/ + 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..f14f4ea00d2d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limP2P.c @@ -0,0 +1,1154 @@ +/* + * 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. + */ + +/*=========================================================================== + 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); +/*------------------------------------------------------------------ + * + * 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, false); + } + + 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) +{ + 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->frame_len = frameLen; + 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); + + 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); + + 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) +{ + 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 status; +} + + +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")); + limP2PActionCnf(pMac, false); + 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 ) + { + limP2PActionCnf(pMac, false); + 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")); + limP2PActionCnf(pMac, false); + 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)); + pMacHdr = (tpSirMacMgmtHdr)pFrame; + /* + * 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 is PMF + */ + 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 (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 + + /* 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) + { + limP2PActionCnf(pMac, (HAL_STATUS_SUCCESS(halstatus)) ? + true : false); + } + 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!" )); + limP2PActionCnf(pMac, false); + 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..7fc993728835 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessActionFrame.c @@ -0,0 +1,2607 @@ +/* + * 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; + 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 + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + switch (pActionHdr->category) + { + case SIR_MAC_ACTION_QOS_MGMT: + 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: + 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 + 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: + { + 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: + 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);) + 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..b53a055c7f11 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c @@ -0,0 +1,1087 @@ +/* + * 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 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->assocRspLen = 0; + } + + 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; + psessionEntry->RICDataLen = 0; + } + 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; + psessionEntry->tspecLen = 0; + } + 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 + /* + * 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 || + (subType == LIM_REASSOC)) +#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."));) + + 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 */ + 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..b86eb352b2df --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c @@ -0,0 +1,308 @@ +/* + * 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 = 0; + } + 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..d0fbfc9db049 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c @@ -0,0 +1,365 @@ +/* + * 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 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: + case eSIR_MAC_PEER_REJECT_MECHANISIM_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));) + break; + } + } + 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..c5602595cf9e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMessageQueue.c @@ -0,0 +1,2431 @@ +/* + * 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) && + /* + * 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 + 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_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; + + //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 */ + + 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; + // 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..1dbacdf5e18d --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -0,0 +1,4911 @@ +/* + * 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; + if(NULL == pMac->lim.gpLimMlmOemDataReq) + { + PELOGE(limLog(pMac, LOGE, FL("Null pointer"));) + goto error; + } + + pStartOemDataReq = vos_mem_malloc(sizeof(*pStartOemDataReq)); + if ( NULL == pStartOemDataReq ) + { + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Could not allocate memory for pStartOemDataReq"));) + goto error; + } + + 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)); + + 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; + 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->data); + vos_mem_free(pStartOemDataReq); + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_pStartOemDataReq 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) + { + 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; + } + + 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; + tLimMlmOemDataReq *data_req = (tLimMlmOemDataReq *)pMsgBuf; + + 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) { + 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 = data_req; + pMac->lim.gpLimMlmOemDataReq->data = data_req->data; + 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..e78980722a09 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c @@ -0,0 +1,5112 @@ +/* + * 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; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + 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; + mlmAssocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; + } +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); + 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) + 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) { + limP2PActionCnf(pMac, false); + 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..e6c2d4b39d93 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c @@ -0,0 +1,502 @@ +/* + * 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 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; + WDA_GET_RX_PAYLOAD_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 = 0; + } + 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..c6d2760f2984 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -0,0 +1,7193 @@ +/* + * 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 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); + +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(*pMlmOemDataReq)); + if ( NULL == pMlmOemDataReq ) + { + limLog(pMac, LOGP, FL("AllocateMemory failed for mlmOemDataReq")); + return; + } + + 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)); + + 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); + + 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; + /* + * 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 supported NSS 1x1: %d"), + psessionEntry->enableHtSmps, + psessionEntry->htSmpsvalue, + psessionEntry->supported_nss_1x1); + + /*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 supported nss 1x1: %d"), + psessionEntry->enableHtSmps, + psessionEntry->htSmpsvalue, + psessionEntry->supported_nss_1x1); + + /** + * 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")); + } + + 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*/ + 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_scan_offload_req(tpAniSirGlobal mac_ctx, + tANI_U32 *msg_buf) +{ + tpPESession pe_session; + tSirMsgQ wma_msg; + tSirRetStatus status; + tSirRoamOffloadScanReq *msg, *req_buffer; + + msg = (tSirRoamOffloadScanReq *)msg_buf; + pe_session = pe_find_session_by_sme_session_id(mac_ctx, + 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; + } + + *req_buffer = *msg; + + vos_mem_zero(&wma_msg, sizeof(tSirMsgQ)); + 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; +} + +/* 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() + * + *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_SCAN_OFFLOAD_REQ: + __lim_process_roam_scan_offload_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; + 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; + 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); + +} + +/** + * 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() + * + *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 */ + if (LIM_IS_IBSS_ROLE(psessionEntry)) { + limUpdateIBssPropAddIEs(pMac, + &psessionEntry->addIeParams.probeRespData_buff, + &psessionEntry->addIeParams.probeRespDataLen, + &pModifyAddIEs->modifyIE); + } + 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 (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); + } + 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..dbbbd2405578 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limProcessTdls.c @@ -0,0 +1,3421 @@ +/* + * 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) ; +} + +/** + * 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 lim_mgmt_tdls_tx_complete(tpAniSirGlobal mac_ctx, + uint32_t tx_complete) +{ + tpPESession session_entry = NULL ; + + 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; +} + +/* + * 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.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, + lim_mgmt_tdls_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.tdls_frm_session_id = 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, + psessionEntry->currentOperChannel)) + 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.tdls_frm_session_id = 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, + lim_mgmt_tdls_tx_complete, + HAL_USE_SELF_STA_REQUESTED_MASK, smeSessionId, false ); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.tdls_frm_session_id = 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 ); + + 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, + psessionEntry->currentOperChannel); + + /* 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.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, + lim_mgmt_tdls_tx_complete, + 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, + lim_mgmt_tdls_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); +#endif + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.tdls_frm_session_id = 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.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, + lim_mgmt_tdls_tx_complete, + 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, + lim_mgmt_tdls_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, + false ); +#endif + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.tdls_frm_session_id = 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, + psessionEntry->currentOperChannel); + + /* 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.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, + lim_mgmt_tdls_tx_complete, + 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, + lim_mgmt_tdls_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); +#endif + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.tdls_frm_session_id = 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.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, + lim_mgmt_tdls_tx_complete, + 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, + lim_mgmt_tdls_tx_complete, + HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME, + smeSessionId, false ); +#endif + + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) + { + pMac->lim.tdls_frm_session_id = 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. + */ + limLog(pMac, LOG1, + FL("supportedChannelWidthSet %x htSupportedChannelWidthSet %x"), + htCaps->supportedChannelWidthSet, + psessionEntry->htSupportedChannelWidthSet); + + pStaDs->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; + 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_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 channel %d from the valid channel list"), + validChan[i]); + 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; +} + + +/** + * 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) +{ + + if (NULL == psessionEntry) + { + limLog(pMac, LOGE, FL("NULL psessionEntry")); + return eSIR_FAILURE; + } + + lim_check_aid_and_delete_peer(pMac, psessionEntry); + + 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/limPropExtsUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c new file mode 100644 index 000000000000..047eb5b8cbf9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limPropExtsUtils.c @@ -0,0 +1,309 @@ +/* + * 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 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; + } + /* 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() ******/ + +/** + * 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..d775e7e6421a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -0,0 +1,6331 @@ +/* + * 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 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; + 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; + bool extracted_ext_cap_flag = false; + tDot11fIEExtCap extracted_ext_cap; + + + + + /* 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 ); + } + + if (addn_ielen) { + + 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; + + // 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! + } + + /* 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 ), + 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_FALSE; + + 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 ) + { + limLog(pMac, LOG1, + FL("Unable to Stripoff ExtCap IE from Probe Rsp")); + } else { + extractedExtCapFlag = eANI_BOOLEAN_TRUE; + } + + 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 && psessionEntry->is_ext_caps_present) { + 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->qosMap = 1; + extractedExtCapFlag = lim_is_ext_cap_ie_present(p_ext_cap); + } + } else { + limLog(pMac, LOG1, + FL("No addn IE or peer dosen't support addnIE for Assoc Req")); + 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 && + 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 + // 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 + if (psessionEntry->is_ext_caps_present) + 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 && + SIR_MAC_GET_RRM(psessionEntry->limCurrentBssCaps)) + 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; + } + if (psessionEntry->is_ext_caps_present) + 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 && + 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 + // 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 + + if (psessionEntry->is_ext_caps_present) + 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..484f87cc3ef6 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c @@ -0,0 +1,3367 @@ +/* + * 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; + psessionEntry->bcnLen = 0; +#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG + PELOG1(limLog(pMac, LOG1, FL("Beacon=%d"), + pSirSmeJoinRsp->beaconLength);) +#endif + } + + if(psessionEntry->assocReq != NULL) + { + pSirSmeJoinRsp->assocReqLength = psessionEntry->assocReqLen; + 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"), + pSirSmeJoinRsp->assocReqLength);) +#endif + } + if(psessionEntry->assocRsp != NULL) + { + pSirSmeJoinRsp->assocRspLength = psessionEntry->assocRspLen; + 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 + + 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 +#ifdef FEATURE_WLAN_ESE + if(psessionEntry->tspecIes != NULL) + { + pSirSmeJoinRsp->tspecIeLen = psessionEntry->tspecLen; + 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; + 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"), + pSirSmeJoinRsp->assocRspLength);) +#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; + 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 + if(psessionEntry->ricData != NULL) + { + vos_mem_free( psessionEntry->ricData); + psessionEntry->ricData = NULL; + psessionEntry->RICDataLen = 0; + } +#endif + +#ifdef FEATURE_WLAN_ESE + if(psessionEntry->tspecIes != NULL) + { + vos_mem_free(psessionEntry->tspecIes); + psessionEntry->tspecIes = NULL; + psessionEntry->tspecLen = 0; + } +#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); + vos_mem_free(MsgQ->bodyptr); + 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..4ffdf9686bf8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limSession.c @@ -0,0 +1,854 @@ +/* + * 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; + 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 */ + 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; + 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; + } + + + 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..dbdf80590e0c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTimerUtils.c @@ -0,0 +1,2277 @@ +/* + * 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" +#include "limApi.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; + + 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); +} /****** 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..18c7866b6fb8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limTypes.h @@ -0,0 +1,1094 @@ +/* + * 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); +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 +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..9b859830b45b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c @@ -0,0 +1,8769 @@ +/* + * 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 + */ + 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; +} + +/** + * 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 new file mode 100644 index 000000000000..bfb9dbf9d2a7 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.h @@ -0,0 +1,673 @@ +/* + * 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); +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/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..4820f645685f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schApi.c @@ -0,0 +1,682 @@ +/* + * 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. + */ + +/* + * + * 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 "limUtils.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; + 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 ) ) + { + 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; + } + addn_ielen = addnIELenWoP2pIe; + + 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 + addn_ielen) <= SIR_MAX_PACKET_SIZE ) + nBytes += addn_ielen; + 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); + + /* 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 ); + + 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 - addn_ielen], &addIE[0], addn_ielen); + + /* 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; +} 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..6969d29322db --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/sch/schBeaconGen.c @@ -0,0 +1,932 @@ +/* + * 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 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, uint8_t *addn_ie, + uint16_t addn_ielen) +{ + tSirRetStatus status = eSIR_FAILURE; + tANI_U8 addIE[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN]; + + if(addn_ielen <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && addn_ielen && + ((addn_ielen + *nBytes) <= maxBeaconSize)) + { + + 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 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 + { + schLog(pMac, LOGE, + FL("Not able to insert NoA because of addn_ielength constraint")); + } + } + } + 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); + } + } + } + + 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; + 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 ) + { + 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 + + if (psessionEntry->limSystemRole != eLIM_STA_IN_IBSS_ROLE) + 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)); + } + } + + } + + 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 ); + 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); + vos_mem_free(addn_ie); + 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; + + if (addn_ielen > 0) + schAppendAddnIE(pMac, psessionEntry, + psessionEntry->pSchBeaconFrameEnd + nBytes, + SCH_MAX_BEACON_SIZE, &nBytes, addn_ie, addn_ielen); + + 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); + vos_mem_free(addn_ie); + 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..52df92410852 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/inc/sapApi.h @@ -0,0 +1,2388 @@ +/* + * 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_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_REMAIN_CHAN_READY, + 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_SendActionCnf sapActionCnf; + 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; + uint16_t tx_leakage_threshold; +} 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); + +VOS_STATUS wlansap_set_tx_leakage_threshold(tHalHandle hal, + uint16 tx_leakage_threshold); + + +#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..50a10feddb1a --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapApiLinkCntl.c @@ -0,0 +1,1405 @@ +/* + * 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 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_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_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); + pMac->sap.SapDfsInfo.is_dfs_cac_timer_running = false; + + /* + * 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 + */ + } + + 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 + */ + sapEvent.event = eWNI_SME_CHANNEL_CHANGE_RSP; + sapEvent.params = 0; + sapEvent.u1 = eCSR_ROAM_INFRA_IND; + sapEvent.u2 = eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE; + + vosStatus = sapFsm(sapContext, &sapEvent); + if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { + halStatus = eHAL_STATUS_FAILURE; + } + break; + } + 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..ce830391b747 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapChSelect.c @@ -0,0 +1,2678 @@ +/* + * 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; + tSapSpectChInfo *pSpectChStartAddr = pSpectInfoParams->pSpectCh; + tSapSpectChInfo *pSpectChEndAddr = + pSpectInfoParams->pSpectCh + pSpectInfoParams->numSpectChans; + + 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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 && + (pExtSpectCh >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + 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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 >= pSpectChStartAddr && + pExtSpectCh <= pSpectChEndAddr)) + { + ++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 < 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)); + } + } +#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..4d747095e7a0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c @@ -0,0 +1,4915 @@ +/* + * 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 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; + 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++) { + 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 <= + mac->sap.SapDfsInfo.tx_leakage_threshold) + { + /* + * 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_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_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 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, + "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; + } + + /* + * 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) + { + /* + * 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; + vos_timer_destroy(&pMac->sap.SapDfsInfo.sap_dfs_cac_timer); + + 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 = 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; + } +} + +/* + * 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..ac7f658faef1 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapModule.c @@ -0,0 +1,4000 @@ +/* + * 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; +} + +/** + * 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/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..733cab96a563 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/BMI/ol_fw.c @@ -0,0 +1,2719 @@ +/* + * 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) +#ifdef DEBUG + int ret; +#endif +#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..dd1b7e8e8c3c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/ol_txrx_dbg.h @@ -0,0 +1,233 @@ +/* + * 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 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 */ +#include "vos_status.h" + +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 ---*/ +VOS_STATUS 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..93db994b2bdf --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config.h @@ -0,0 +1,255 @@ +/* + * 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 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, + * 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 +/* + * 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..f59da18ee3b3 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wlan_tgt_def_config_hl.h @@ -0,0 +1,293 @@ +/* + * 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 16 +/* + * 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 +/* + * 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..e1f7334aea29 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/wmi_unified.h @@ -0,0 +1,12076 @@ +/* + * 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_TDLS_CONN_TRACKER_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_TDLS_CONN_TRACKER_EVENT, + 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..0491f2d9c251 --- /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_ 184 + +/** 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..566679558eac --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -0,0 +1,3103 @@ +/* + * 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, 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); +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_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 +typedef struct { + hif_irq_type type; + 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 +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; + + 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; + } + + 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 +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) { + hif_irq_record(HIF_IRQ_END, sc); + 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) { + hif_irq_record(HIF_TASKLET_END, sc); + 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__); +} + +#ifdef TARGET_RAMDUMP_AFTER_KERNEL_PANIC +#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); + + if (pm_state == HIF_PM_RUNTIME_STATE_ON || + pm_state == HIF_PM_RUNTIME_STATE_NONE) + return true; + + 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 */ + +#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; + + ret = hif_pci_check_soc_status(sc); + + if (ret) { + pr_err("%s: SOC wakeup Failed\n", __func__); + return; + } + + ret = dump_CE_register(scn); + + if (ret) { + pr_err("%s: Failed to dump Copy Engine Registers\n", __func__); + return; + } + + dump_CE_debug_register(sc); +} +#else +static void hif_dump_soc_and_ce_registers(struct hif_pci_softc *sc) +{ +} +#endif + +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); + + 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); +} + +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 + +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; + + hif_irq_record(HIF_SUSPEND_START, sc); + + 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); + } + + 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)) { + pr_err("%s: Fail to enable wake IRQ!\n", __func__); + ret = -EAGAIN; + goto out; + } + + pr_debug("%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); + } + + hif_irq_record(HIF_SUSPEND_END, sc); + + 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_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); + 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++; + } + + hif_irq_record(HIF_RESUME, sc); + + 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_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: + 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..7fb5b37ca182 --- /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 = 0; + 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..29c65cdb7494 --- /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))) + 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")); + + 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 */ + 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); + } + + 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..a50b19543f5c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/regdomain_common.h @@ -0,0 +1,1875 @@ +/* + * 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 */ + APL13 = 0x1170, /* Algeria */ + + 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 }, + {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 }, + {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, 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 }, + {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, 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 }, + {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, ETSI1_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 + }, + + {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), + 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..869cdb8d18ea --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c @@ -0,0 +1,33739 @@ +/* + * 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 + +#define WMI_MAX_MHF_ENTRIES 32 + +#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 (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)) { + + 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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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); + wmi_buf_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, 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; + + 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 (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, + 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) { + wmi_buf_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); + iface->handle = NULL; + wma_handle->interfaces[vdev_id].is_vdev_valid = false; + 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); + 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; +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__); + wmi_buf_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); + wmi_buf_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"); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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"); + wmi_buf_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; + u_int8_t vdev_id; + + 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; + } + vdev_id = self_sta_req->sessionId; + + 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].vdev_active = TRUE; + 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); + } + } + 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, + 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_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. + */ + 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) + wmi_buf_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) + wmi_buf_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_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); + 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) + wmi_buf_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) + wmi_buf_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: + 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: + 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; + + 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; + 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__); + + wmi_buf_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__); + wmi_buf_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); + 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; + 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; + } + + 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); + wmi_buf_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); + wmi_buf_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__); + wmi_buf_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); + wmi_buf_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); + + wmi_buf_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"); + wmi_buf_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: + 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, + 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__); + wmi_buf_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"); + wmi_buf_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); + wmi_buf_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) { + wmi_buf_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) { + wmi_buf_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) { + wmi_buf_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__); + wmi_buf_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 (!((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); + } + } +} + +#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); + wmi_buf_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_TDLS + WMI_TDLS_PEER_EVENTID_param_tlvs tdls_param; +#endif +#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; + +#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; + } + + 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"; + case WOW_TDLS_CONN_TRACKER_EVENT: + return "WOW_TDLS_CONN_TRACKER_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)); + 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) { + vos_trigger_recovery(); + } else { + VOS_BUG(0); + } +#else + VOS_BUG(0); +#endif + } else { + WMA_LOGE("%s: LOGP is in progress, ignore!", __func__); + } + + 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 + +#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) { + 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 || !startOemDataReq->data) { + 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, + (startOemDataReq->data_len + 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, + startOemDataReq->data_len); + cmd += WMI_TLV_HDR_SIZE; + vos_mem_copy(cmd, &startOemDataReq->data[0], + startOemDataReq->data_len); + + WMA_LOGI("%s: Sending OEM Data Request to target, data len (%d)", + __func__, startOemDataReq->data_len); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, + (startOemDataReq->data_len + + WMI_TLV_HDR_SIZE), + WMI_OEM_REQ_CMDID); + + if (ret != EOK) { + WMA_LOGE("%s:wmi cmd send failed", __func__); + wmi_buf_free(buf); + } + +out: + /* free oem data req buffer received from UMAC */ + 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 + * 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; + wmi_buf_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__); + wmi_buf_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; + wmi_buf_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; + wmi_buf_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"); + wmi_buf_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"); + wmi_buf_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_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 + 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) { + wmi_buf_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); + wmi_buf_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__); + wmi_buf_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); + 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); + 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__); + wmi_buf_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; + } + + 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); + + 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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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; + } + + 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) { + 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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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; +} + +/** +* 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 : + * 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_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); + 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; + 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 */ + 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); + } + } + /* 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) { + wmi_buf_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 */ + +/* 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 : + * 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 + + 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__); + 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); + + /* 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( + 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; + 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, + 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); + wmi_buf_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_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); + + 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"); + wmi_buf_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)) { + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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__); + wmi_buf_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..dc9737d21390 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h @@ -0,0 +1,1692 @@ +/* + * 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.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 */ + bool vdev_active; + 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; + bool is_vdev_valid; + +}; + +#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; + + txFailIndCallback hddTxFailCb; + +#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; + + 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; + 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; + uint32_t fine_time_measurement_cap; +}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..8e62ca2fb5df --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified.c @@ -0,0 +1,1317 @@ +/* + * 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_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) +{ + 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: + htc_tag = (A_UINT16) wmi_set_htc_tx_tag(wmi_handle, + buf, cmd_id); + +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..dca9e4bbef6b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/csrApi.h @@ -0,0 +1,1868 @@ +/* + * 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 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_REMAIN_CHAN_READY, + //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 + + 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, + 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_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, + 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; + uint8_t qos; + 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..70f21ffe1ca5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/oemDataApi.h @@ -0,0 +1,143 @@ +/* + * 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; + uint8_t data_len; + uint8_t *data; +} 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..fd5ac882ff99 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/smeInternal.h @@ -0,0 +1,235 @@ +/* + * 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) + +/* 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; + 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; + tSmePeerInfoHddCbkInfo peerInfoParams; +#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..3ee45c6a08c4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/inc/sme_Api.h @@ -0,0 +1,4489 @@ +/* + * 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_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 + + \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); + +/** + * 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 + \param hHal - The handle returned by macOpen + \param rateUpdateParams - Pointer to rate update params + \return eHalStatus + ---------------------------------------------------------------------------*/ +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 + * 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 */ + +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 + \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_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); + +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); + +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/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..3251b13d6d3e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrApiRoam.c @@ -0,0 +1,19711 @@ +/* + * 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 (vos_is_dsrc_channel(vos_chan_to_freq( + pScan->base20MHzChannels.channelList[i]))) + continue; + 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; + } + 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; + } + 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; + pParam->enableHtSmps = pMac->roam.configParam.enableHtSmps; + pParam->htSmps = pMac->roam.configParam.htSmps; + 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; + 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 + /* + * 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 ) ) + { + /* + * 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; + + 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; + } + + 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]) || + ((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) +{ + uint8_t num_chan_temp = 0; + int i; + eHalStatus status; + + status = ccmCfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, + (tANI_U8 *)pChannels, + 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) +{ + 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) + { + vos_mem_set(pTlStats, sizeof(*pTlStats), 0); + + //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) + { + 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))) + { + 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; +} + +VOS_STATUS csr_roam_send_rso_cmd(tpAniSirGlobal pMac, tANI_U8 session_id, + tSirRoamOffloadScanReq *pRequestBuf) +{ + eHalStatus status; + + 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("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) +{ + 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 ((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]); + } + + 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 PE", __func__); + return eHAL_STATUS_FAILURE; + } + else + { + if (ROAM_SCAN_OFFLOAD_START == command) + bRoamScanOffloadStarted = VOS_TRUE; + else if (ROAM_SCAN_OFFLOAD_STOP == command) + bRoamScanOffloadStarted = VOS_FALSE; + } + /* 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 = {{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 + 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); + + 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)); + 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->modifyIE.oui_length = pModifyIE->oui_length; + + 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..ebb9d7d24a83 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrNeighborRoam.c @@ -0,0 +1,6342 @@ +/* + * 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 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(%d) or uOsRequestedHandoff(%d) is not set. Ignore it "), + pNeighborRoamInfo->neighborRoamState, pNeighborRoamInfo->uOsRequestedHandoff); + 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..d288d91577a9 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/csr/csrUtil.c @@ -0,0 +1,6067 @@ +/* + * 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 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_REMAIN_CHAN_READY); + 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..a8a4534477ed --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/oemData/oemDataApi.c @@ -0,0 +1,391 @@ +/* + * 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. + */ + +#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)) + { + 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); + } + 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; + tOemDataReq *cmd_req; + + do + { + if( !CSR_IS_SESSION_VALID( pMac, sessionId ) ) + { + status = eHAL_STATUS_FAILURE; + break; + } + + pMac->oemData.oemDataReqID = *(pOemDataReqID); + + 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; + + 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 + { + 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; + + smsLog(pMac, LOGW, "OEM_DATA: entering Function %s", __func__); + + if (!pOemDataReq) { + smsLog(pMac, LOGE, FL("oem data req is NULL")); + return eHAL_STATUS_INVALID_PARAMETER; + } + + 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; + } + + 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; +} + +/* --------------------------------------------------------------------------- + \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; + tOemDataReq *req; + 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); + req = &(pCommand->u.oemDataCmd.oemDataReq); + vos_mem_free(req->data); + 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..f30075a217ac --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/p2p/p2p_Api.c @@ -0,0 +1,448 @@ +/* + * 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. + */ + + + + +#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 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_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..0d4d26594bc0 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/rrm/sme_rrm.c @@ -0,0 +1,1631 @@ +/* + * 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 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 + } + + smsLog(pMac, LOG1, FL("RRM Measurement Done %d"), measurementDone); + 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); + 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; + } + pScanResult = pNextResult; //sme_ScanResultGetNext(hHal, pResult); + if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC) + break; + } + + 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 + 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_U32 sessionId; + + /* Get the session id */ + status = csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)pNeighborRpt->bssId, + &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..b364a303e82b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SME/src/sme_common/sme_Api.c @@ -0,0 +1,17954 @@ +/* + * 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_remainOnChnReady( 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); + 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 + + 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 +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; +} + +/*-------------------------------------------------------------------------- + + \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_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_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) + { + 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_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 + 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 + +/** + * 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 + + \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) + continue; + else + { + pTdlsPeerStateParams->peerCap.peerChan[num].dfsSet = + VOS_FALSE; + } + + if (vos_nv_skip_dsrc_dfs_2g(chanId, NV_CHANNEL_SKIP_DSRC)) + continue; + + 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")); + } + 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; +} + +/** + * 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; + 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); + + 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) { + 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 SIR_HAL_SET_MIRACAST 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; + } + + 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/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..1171f070a60b --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SVC/src/logging/wlan_logging_sock_svc.c @@ -0,0 +1,800 @@ +/* + * 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. + */ + +/****************************************************************************** + * 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" +#include +#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; + struct timeval tv; + struct rtc_time tm; + unsigned long local_time; + + 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 + * 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 [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; + + 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..b9ba59a8d4eb --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -0,0 +1,1063 @@ +/* + * 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_REMAIN_ON_CHN_RDY_IND); + CASE_RETURN_STRING(eWNI_SME_SEND_ACTION_FRAME_IND); + 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_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); +#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); + CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_CB); + 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_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); + 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..a9ad11acd3ec --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/SYS/legacy/src/utils/src/parserApi.c @@ -0,0 +1,5734 @@ +/* + * 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 && + 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 (!psessionEntry || LIM_IS_STA_ROLE(psessionEntry)) { + p_ext_cap->fine_time_meas_initiator = + (pMac->fine_time_meas_cap & WMI_FW_STA_RTT_INITR) ? 1 : 0; + p_ext_cap->fine_time_meas_responder = + (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 & WMI_FW_AP_RTT_INITR) ? 1 : 0; + p_ext_cap->fine_time_meas_responder = + (pMac->fine_time_meas_cap & WMI_FW_AP_RTT_RESPR) ? 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, + uint8_t curr_oper_channel) +{ + 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 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))) { + 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; + if (pBies->ExtCap.present) { + pBeaconStruct->ExtCap.present = 1; + vos_mem_copy( &pBeaconStruct->ExtCap, &pBies->ExtCap, + sizeof(tDot11fIEExtCap)); + } + + 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..6c8d527ae618 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/TL/inc/wlan_qct_tl.h @@ -0,0 +1,3015 @@ +/* + * 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. + */ + + +#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 + * + */ +VOS_STATUS 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 VOS_STATUS WLANTL_Get_llStats +( + uint8_t sessionId, + char *buffer, + uint16_t length +) +{ + return VOS_STATUS_SUCCESS; +} + +#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..6b4e47910b68 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/FWLOG/dbglog_host.c @@ -0,0 +1,4262 @@ +/* + * 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..fa296a21c96c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_ac.c @@ -0,0 +1,418 @@ +/* + * 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 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 A_ERROR; + } + + 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 A_ERROR; + } + + 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 A_ERROR; + } + } + + 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 A_ERROR; + } + /* WMI command to enable pktlog on the firmware */ + if (pktlog_enable_tgt(scn, log_state)) { + 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; + } + } 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)) { + adf_os_print("%s: Cannot unsubscribe pktlog from the WDI\n", + __func__); + return A_ERROR; + } + } + + 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..5f50f77c97aa --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/UTILS/PKTLOG/pktlog_internal.c @@ -0,0 +1,633 @@ +/* + * 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; + } + 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; + 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 A_ERROR; + } + /* 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..ca93571daaf8 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/i_vos_lock.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. + */ + +#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 + bool is_initialized; +} 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..80646a6bfaa4 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_mq.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2013-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. + */ + +#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; + + +#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 + + 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 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 + 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 + + --------------------------------------------------------------------------*/ +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); +} + + +/**--------------------------------------------------------------------------- + + \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..7bc8088a41a8 --- /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_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); + +#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..76bb1ce09e42 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_utils.h @@ -0,0 +1,187 @@ +/* + * 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); +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/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..53e62f8f8a08 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c @@ -0,0 +1,2975 @@ +/* + * 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" + +#include "vos_utils.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; + + 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 */ + + 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() */ + +/** + * 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; + 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)); + + 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; + +} + + +/**--------------------------------------------------------------------------- + + \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..f08c9e45a2ea --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_lock.c @@ -0,0 +1,768 @@ +/* + * 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 (!pLock->is_initialized) { +#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 + 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; + } +} + +/** + * 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->is_initialized) && (pLock->lock.name)) + return pLock->lock.name; +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + if ((pLock->is_initialized) && (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) +{ + 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); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock(&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; + } +} + +/*-------------------------------------------------------------------------- + + \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) +{ + 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); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_timeout(&pLock->lock, msecs_to_jiffies(msec)); +#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; + } +} + +/*-------------------------------------------------------------------------- + + \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) +{ + 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); +#elif defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK) + 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; + + } +} + +/*-------------------------------------------------------------------------- + + \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 (pLock->is_initialized) { +#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 + 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) +{ + 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..81c43598594e --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_mq.c @@ -0,0 +1,274 @@ +/* + * 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. + */ + +/**========================================================================= + + \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() */ + +/** + * 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); +} + +/*--------------------------------------------------------------------------- + + \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..1faebc9bd76c --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_nvitem.c @@ -0,0 +1,1915 @@ +/* + * 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_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_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; + + 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; + } + } + + 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..e097ce759fd8 --- /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); + + INIT_COMPLETION(pSchedContext->ResumeMcEvent); + /* Mc Thread Suspended */ + complete(&pHddCtx->mc_sus_event_var); + + 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); + INIT_COMPLETION(pSchedContext->ResumeTlshimRxEvent); + complete(&pSchedContext->SuspndTlshimRxEvent); + 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..5fe18ffa82c5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_sched.h @@ -0,0 +1,681 @@ +/* + * 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); +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); +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..adf15999f495 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_utils.c @@ -0,0 +1,1248 @@ +/* + * 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; +} + +/** + * 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 new file mode 100644 index 000000000000..fe2d200f731f --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/legacy/halMsgApi.h @@ -0,0 +1,1640 @@ +/* + * 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; + uint8_t data_len; + uint8_t *data; +} 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..cb1b1e61e2a5 --- /dev/null +++ b/drivers/staging/qcacld-2.0/CORE/WDA/inc/wlan_qct_wda.h @@ -0,0 +1,1265 @@ +/* + * 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); + +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); + +/* + * 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; + + WDA_txFailIndCallback txFailIndCallback; +} 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_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 +#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 + +/* 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 +#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 + +#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); + +#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..41a30f4154df --- /dev/null +++ b/drivers/staging/qcacld-2.0/Kbuild @@ -0,0 +1,1448 @@ +# 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 \ + -DWLAN_VOWIFI_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 +endif + +ifeq ($(CONFIG_QCACLD_SPAMMY_DEBUG),y) +CDEFINES += -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..a925b6464d9e --- /dev/null +++ b/drivers/staging/qcacld-2.0/Kconfig @@ -0,0 +1,76 @@ +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 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 + +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/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..c274858771bc --- /dev/null +++ b/drivers/staging/qcacld-2.0/wcnss/inc/wlan_nv.h @@ -0,0 +1,839 @@ +/* + * 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, + NV_CHANNEL_SKIP_DSRC, + NV_CHANNEL_SKIP_2G +}; +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 + 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; } 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; 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+ */ 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_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, 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; 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; 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, 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); 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); 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 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_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 = { diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c index 87a9733dc25a..a43f61ed08e7 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; 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_kcal_ctrl.c b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c new file mode 100644 index 000000000000..4ea14ea58e0e --- /dev/null +++ b/drivers/video/msm/mdss/mdss_mdp_kcal_ctrl.c @@ -0,0 +1,636 @@ +/* + * 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 + +#include "mdss_mdp.h" + +#define DEF_PCC 0x100 +#define DEF_PA 0xff +#define PCC_ADJ 0x80 + +struct kcal_lut_data { + 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 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; + /* 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 ret; +} + +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; + + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_display_commit(); + + 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; + + mdss_mdp_kcal_update_pcc(lut_data); + mdss_mdp_kcal_display_commit(); + + 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; + + 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; +} + +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; + + //disable + lut_data->invert = 0; + + //mdss_mdp_kcal_update_igc(lut_data); + //mdss_mdp_kcal_display_commit(); + + 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; + + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); + + 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; + + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); + + 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; + + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); + + 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; + + mdss_mdp_kcal_update_pa(lut_data); + mdss_mdp_kcal_display_commit(); + + 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 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; + + 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(); + + 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__); + return ret; + } + + return 0; +} + +static int kcal_ctrl_remove(struct platform_device *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); + + 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); +} + +module_init(kcal_ctrl_init); +module_exit(kcal_ctrl_exit); 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; } 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)) { 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/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; 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))) 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/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; 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 5384007de6f8..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,6 +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)) @@ -3767,6 +3781,20 @@ static long do_unlinkat(int dfd, const char __user *pathname) inode = dentry->d_inode; if (d_is_negative(dentry)) goto slashes; +#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) @@ -3776,6 +3804,13 @@ static long do_unlinkat(int dfd, const char __user *pathname) dput(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); +#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; @@ -3813,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/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; } 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/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; diff --git a/fs/sdcardfs/Kconfig b/fs/sdcardfs/Kconfig new file mode 100644 index 000000000000..1498fa906f1a --- /dev/null +++ b/fs/sdcardfs/Kconfig @@ -0,0 +1,19 @@ +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_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..b5f9d0f8219c --- /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..2709d8a59518 --- /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" +#include + +/* 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; + 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" + " 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; + + /* 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) + 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: + current->fs = saved_fs; + free_fs_struct(copied_fs); + 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); + 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" + " 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; + + /* 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) { + 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")))) { + set_fs_pwd(current->fs, &lower_path); + touch_err = touch(".nomedia", 0664); + if (touch_err) { + printk(KERN_ERR "sdcardfs: failed to create .nomedia in %s: %d\n", + lower_path.dentry->d_name.name, touch_err); + goto out; + } + } +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); +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; +} + +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, +#ifdef SDCARD_FS_XATTR + .setxattr = sdcardfs_setxattr, + .getxattr = sdcardfs_getxattr, + .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. + .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 + .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. + .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 + .get_lower_inode = sdcardfs_get_lower_inode, +}; diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c new file mode 100644 index 000000000000..425058ec8cba --- /dev/null +++ b/fs/sdcardfs/lookup.c @@ -0,0 +1,397 @@ +/* + * 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 */ + err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0, + &lower_path); + + /* check for other cases */ + 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 */ + 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..dbfb9b52e5d2 --- /dev/null +++ b/fs/sdcardfs/main.c @@ -0,0 +1,420 @@ +/* + * 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_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, 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_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; + 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..b8b68e191473 --- /dev/null +++ b/fs/sdcardfs/sdcardfs.h @@ -0,0 +1,543 @@ +/* + * 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 { + 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 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); +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); +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; + 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..3d3e082766a6 --- /dev/null +++ b/fs/sdcardfs/super.c @@ -0,0 +1,285 @@ +/* + * 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. + */ + +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(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) { + 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, + .unlink_callback = sdcardfs_propagate_unlink, +}; 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; +} 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; 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 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) diff --git a/include/linux/fs.h b/include/linux/fs.h index 6894e9ecc982..371aaf7e65a7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -133,6 +133,15 @@ 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) + +/* File page don't need to be cached, for stackable filesystem's lower file */ +#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) @@ -1427,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. @@ -1521,6 +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 { @@ -1560,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, @@ -1601,6 +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); +#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/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/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) 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); 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; 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")) 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; 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; } diff --git a/mm/mmap.c b/mm/mmap.c index 48f3ecf387bd..b18086f67437 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1276,6 +1276,12 @@ 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) apply_app_setting_bit(file); 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; 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; /* 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) { 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; } diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 20de0118c98e..5344ac34eaac 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -154,6 +154,27 @@ 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) { + 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) { + ca->epoch_start += delta; + if (after(ca->epoch_start, now)) + ca->epoch_start = now; + } + return; + } +} + /* calculate the cubic root of x using a table lookup followed by one * Newton-Raphson iteration. * Avg err ~= 0.195% @@ -216,6 +237,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 +311,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; @@ -440,6 +469,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", 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); } 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) 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))) 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, 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 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/gc.c b/security/keys/gc.c index c7952375ac53..addf060399e0 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -134,6 +134,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys) kdebug("- %u", key->serial); key_check(key); + /* 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); /* deal with the user's key tracking and quota */ @@ -148,10 +154,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); 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 */ 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: 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 = { 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; } 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/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/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); diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 96a7cbb46b6d..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, @@ -12504,6 +12509,169 @@ static struct regulator *tasha_codec_find_ondemand_regulator( return NULL; } +#ifdef CONFIG_SOUND_CONTROL +static 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 < -84 || input_l > 20) + input_l = 0; + + 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); + 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 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) +{ + 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; + 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", (int)vol); +} + +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); + 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; + 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, + &headphone_pa_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 +12682,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 +13397,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: